﻿// -------------------------------------------------------------------------------------------------------------------------------
// <copyright file="TestAssign.cs" company="Exul">
//     Copyright (c) Exul. All rights reserved.
// </copyright>
// <author>
//     Exul
// </author>
// -------------------------------------------------------------------------------------------------------------------------------

namespace ExulLibrary.Mathematics.LinearAlgebra.Sequential.Tests.CMDenseMatrixTest
{
    #region Usings

    using System;

    using NUnit.Framework;

    #endregion

    /// <summary>
    ///     Test suite for <see cref="CMDenseMatrixExtensions.Assign{T}(CMDenseMatrix{T},CMDenseMatrix{T})"/>.
    /// </summary>
    [TestFixture]
    [Category("ExulLibrary.Mathematics.LinearAlgebra.Sequential.CMDenseMatrixExtensions")]
    public sealed class TestAssign
    {
        /// <summary>
        ///     Tests the method when source and target parameters have the same size.
        /// </summary>
        [Test]
        public void WhenSourceAndTargetHaveTheSameSize()
        {
            // Arrange
            var source = new CMDenseMatrix<object>(
                new[]
                {
                    new[] { new object(), new object() },
                    new[] { new object(), new object() },
                    new[] { new object(), new object() }
                });
            var target = new CMDenseMatrix<object>(
                new[]
                {
                    new[] { new object(), new object() },
                    new[] { new object(), new object() },
                    new[] { new object(), new object() }
                });

            // Act
            target.Assign(source);

            // Assert
            Assert.That(target.Values, Is.Not.SameAs(source.Values));
            Assert.That(target.Values[0][0], Is.SameAs(source.Values[0][0]));
            Assert.That(target.Values[0][1], Is.SameAs(source.Values[0][1]));
            Assert.That(target.Values[1][0], Is.SameAs(source.Values[1][0]));
            Assert.That(target.Values[1][1], Is.SameAs(source.Values[1][1]));
            Assert.That(target.Values[2][0], Is.SameAs(source.Values[2][0]));
            Assert.That(target.Values[2][1], Is.SameAs(source.Values[2][1]));
        }

        /// <summary>
        ///     Tests the method when source parameter has less count of rows than target parameter.
        /// </summary>
        [Test]
        public void WhenSourceHasLessRowsCountThanTarget()
        {
            // Arrange
            var sourceData = new[]
                             {
                                 new[] { new object() },
                                 new[] { new object() },
                                 new[] { new object() }
                             };
            var source = new CMDenseMatrix<object>(sourceData);
            var targetData = new[]
                             {
                                 new[] { new object(), new object() },
                                 new[] { new object(), new object() },
                                 new[] { new object(), new object() }
                             };
            var target = new CMDenseMatrix<object>(targetData);
            var expectedResult = new[]
                                 {
                                     new[] { sourceData[0][0], targetData[0][1] },
                                     new[] { sourceData[1][0], targetData[1][1] },
                                     new[] { sourceData[2][0], targetData[2][1] }
                                 };

            // Act
            target.Assign(source);

            // Assert
            Assert.That(target.Values, Is.Not.SameAs(source.Values));
            Assert.That(target.Values[0][0], Is.SameAs(expectedResult[0][0]));
            Assert.That(target.Values[1][0], Is.SameAs(expectedResult[1][0]));
            Assert.That(target.Values[2][0], Is.SameAs(expectedResult[2][0]));
            Assert.That(target.Values[0][1], Is.SameAs(expectedResult[0][1]));
            Assert.That(target.Values[1][1], Is.SameAs(expectedResult[1][1]));
            Assert.That(target.Values[2][1], Is.SameAs(expectedResult[2][1]));
        }

        /// <summary>
        ///     Tests the method when source parameter has greater count of rows than target parameter.
        /// </summary>
        [Test]
        public void WhenSourceHasGreaterRowsCountThanTarget()
        {
            // Arrange
            var sourceData = new[]
                             {
                                 new[] { new object(), new object(), new object() },
                                 new[] { new object(), new object(), new object() },
                                 new[] { new object(), new object(), new object() }
                             };
            var source = new CMDenseMatrix<object>(sourceData);
            var target = new CMDenseMatrix<object>(
                new[]
                {
                    new[] { new object(), new object() },
                    new[] { new object(), new object() },
                    new[] { new object(), new object() }
                });
            var expectedResult = new[]
                                 {
                                     new[] { sourceData[0][0], sourceData[0][1] },
                                     new[] { sourceData[1][0], sourceData[1][1] },
                                     new[] { sourceData[2][0], sourceData[2][1] }
                                 };

            // Act
            target.Assign(source);

            // Assert
            Assert.That(target.Values, Is.Not.SameAs(source.Values));
            Assert.That(target.Values[0][0], Is.SameAs(expectedResult[0][0]));
            Assert.That(target.Values[1][0], Is.SameAs(expectedResult[1][0]));
            Assert.That(target.Values[2][0], Is.SameAs(expectedResult[2][0]));
            Assert.That(target.Values[0][1], Is.SameAs(expectedResult[0][1]));
            Assert.That(target.Values[1][1], Is.SameAs(expectedResult[1][1]));
            Assert.That(target.Values[2][1], Is.SameAs(expectedResult[2][1]));
        }

        /// <summary>
        ///     Tests the method when source parameter has less count of columns than target parameter.
        /// </summary>
        [Test]
        public void WhenSourceHasLessColumnsCountThanTarget()
        {
            // Arrange
            var sourceData = new[]
                             {
                                 new[] { new object(), new object() },
                                 new[] { new object(), new object() }
                             };
            var source = new CMDenseMatrix<object>(sourceData);
            var targetData = new[]
                             {
                                 new[] { new object(), new object() },
                                 new[] { new object(), new object() },
                                 new[] { new object(), new object() }
                             };
            var target = new CMDenseMatrix<object>(targetData);

            var expectedResult = new[]
                                 {
                                     new[] { sourceData[0][0], sourceData[0][1] },
                                     new[] { sourceData[1][0], sourceData[1][1] },
                                     new[] { targetData[2][0], targetData[2][1] }
                                 };

            // Act
            target.Assign(source);

            // Assert
            Assert.That(target.Values, Is.Not.SameAs(source.Values));
            Assert.That(target.Values[0][0], Is.SameAs(expectedResult[0][0]));
            Assert.That(target.Values[1][0], Is.SameAs(expectedResult[1][0]));
            Assert.That(target.Values[2][0], Is.SameAs(expectedResult[2][0]));
            Assert.That(target.Values[0][1], Is.SameAs(expectedResult[0][1]));
            Assert.That(target.Values[1][1], Is.SameAs(expectedResult[1][1]));
            Assert.That(target.Values[2][1], Is.SameAs(expectedResult[2][1]));
        }

        /// <summary>
        ///     Tests the method when source parameter has greater count of columns than target parameter.
        /// </summary>
        [Test]
        public void WhenSourceHasGreaterColumnsCountThanTarget()
        {
            // Arrange
            var sourceData = new[]
                             {
                                 new[] { new object(), new object() },
                                 new[] { new object(), new object() },
                                 new[] { new object(), new object() },
                                 new[] { new object(), new object() }
                             };
            var source = new CMDenseMatrix<object>(sourceData);
            var target = new CMDenseMatrix<object>(
                new[]
                {
                    new[] { new object(), new object() },
                    new[] { new object(), new object() },
                    new[] { new object(), new object() }
                });

            var expectedResult = new[]
                                 {
                                     new[] { sourceData[0][0], sourceData[0][1] },
                                     new[] { sourceData[1][0], sourceData[1][1] },
                                     new[] { sourceData[2][0], sourceData[2][1] }
                                 };

            // Act
            target.Assign(source);

            // Assert
            Assert.That(target.Values, Is.Not.SameAs(source.Values));
            Assert.That(target.Values[0][0], Is.SameAs(expectedResult[0][0]));
            Assert.That(target.Values[1][0], Is.SameAs(expectedResult[1][0]));
            Assert.That(target.Values[2][0], Is.SameAs(expectedResult[2][0]));
            Assert.That(target.Values[0][1], Is.SameAs(expectedResult[0][1]));
            Assert.That(target.Values[1][1], Is.SameAs(expectedResult[1][1]));
            Assert.That(target.Values[2][1], Is.SameAs(expectedResult[2][1]));
        }

#if SAFE

        /// <summary>
        ///     Tests the method when source parameter is <see langword="null"/>.
        /// </summary>
        [Test]
        public void WhenSourceIsNull()
        {
            // Arrange
            var target = new CMDenseMatrix<object>(
                new[]
                {
                    new object[2],
                    new object[2],
                    new object[2]
                });

            // Act and Assert
            Assert.That(
                () => target.Assign(null),
                Throws.TypeOf<ArgumentNullException>().With.Property("ParamName").EqualTo("source"));
        }

        /// <summary>
        ///     Tests the method when target parameter is <see langword="null"/>.
        /// </summary>
        [Test]
        public void WhenTargetIsNull()
        {
            // Arrange
            var source = new CMDenseMatrix<object>(
                new[]
                {
                    new object[2],
                    new object[2],
                    new object[2]
                });

            // Act and Assert
            Assert.That(
                () => CMDenseMatrixExtensions.Assign(null, source),
                Throws.TypeOf<ArgumentNullException>().With.Property("ParamName").EqualTo("target"));
        }

#endif
    }
}